#include <tools.h>
#include <standard/geometrymath.h>
#include <standard/filewriter.h>
#include "sceneobjects/sceneobjectmanager.h"
#include "sceneobjects/sceneobject.h"
#include "scene/editorscene.h"
#include "scene/sceneobjectnavigationmap.h"

CSceneObjectManager::CSceneObjectManager(){
    m_pEditorScene = NULL;
    m_nUUID = 10000;
}
CSceneObjectManager::~CSceneObjectManager(){

}
void CSceneObjectManager::Init( const char* strResourceSpace, class CEditorScene* pEditorScene ){
    m_strResourceSpace = strResourceSpace;
    m_pEditorScene = pEditorScene;
}
bool32 CSceneObjectManager::Save( CFileWriter *pFileWriter ){
    char _strTextBuff[ 1024 ];
	int32 _nTextLen;
    _nTextLen = snprintf( _strTextBuff, 1024, "<sceneobject>\n" );
    pFileWriter->AddText( _strTextBuff, _nTextLen );

    for( map<uint32, CSceneObject* >::iterator it = m_vSceneObjectList.begin();
         it != m_vSceneObjectList.end(); it++ ){
        CSceneObject* _pSO = it.second();
        float* _pPos = _pSO->m_vPosition;
        float* _pRotation = _pSO->m_vRotation;
        float* _pScation = _pSO->m_vScale;
        if( _pSO->m_strExtData.empty() ){
            _nTextLen = snprintf( _strTextBuff, 1024, "<item id=\"%u\"type=\"%d\"gridx=\"%d\"gridy=\"%d\"name=\"%s\"file=\"%s\"celltype=\"%d\"rotationtype=\"%d\"initscale=\"%.4f\"helperradius=\"%.4f\"position=\"%.4f,%.4f,%.4f\"rotation=\"%.4f,%.4f,%.4f\"scale=\"%.4f,%.4f,%.4f\"/>\n",
                                  _pSO->m_nID, _pSO->m_eSceneObjectType, _pSO->m_sMapGridPos.X,_pSO->m_sMapGridPos.Y, _pSO->m_strName, _pSO->m_strFileName, _pSO->m_nCellType, _pSO->m_nRotationType, _pSO->m_fInitScale, 
                                  _pSO->m_fHelperRadius, _pPos[0],_pPos[1],_pPos[2], _pRotation[0],_pRotation[1],_pRotation[2],_pScation[0], _pScation[1], _pScation[2] );
            pFileWriter->AddText( _strTextBuff, _nTextLen );
        }else{
            _nTextLen = snprintf( _strTextBuff, 1024, "<item id=\"%u\"type=\"%d\"gridx=\"%d\"gridy=\"%d\"name=\"%s\"file=\"%s\"celltype=\"%d\"rotationtype=\"%d\"initscale=\"%.4f\"helperradius=\"%.4f\"position=\"%.4f,%.4f,%.4f\"rotation=\"%.4f,%.4f,%.4f\"scale=\"%.4f,%.4f,%.4f\">\n",
                                  _pSO->m_nID, _pSO->m_eSceneObjectType, _pSO->m_sMapGridPos.X,_pSO->m_sMapGridPos.Y, _pSO->m_strName, _pSO->m_strFileName, _pSO->m_nCellType, _pSO->m_nRotationType, _pSO->m_fInitScale, 
                                  _pSO->m_fHelperRadius, _pPos[0],_pPos[1],_pPos[2], _pRotation[0],_pRotation[1],_pRotation[2],_pScation[0], _pScation[1], _pScation[2] );
            pFileWriter->AddText( _strTextBuff, _nTextLen );
            _nTextLen = snprintf( _strTextBuff, 1024, "<![CDATA[%s]]>\n", _pSO->m_strExtData.c_str() );
            pFileWriter->AddText( _strTextBuff, _nTextLen );
            _nTextLen = snprintf( _strTextBuff, 1024, "</item>\n", _pSO->m_strExtData.c_str() );
            pFileWriter->AddText( _strTextBuff, _nTextLen );
        }
    }
    _nTextLen = snprintf( _strTextBuff, 1024, "</sceneobject>\n" );
    pFileWriter->AddText( _strTextBuff, _nTextLen );
    return True;
}
bool32 CSceneObjectManager::Open( const char* strResourceSpace, CEditorScene* pEditorScene, CSceneObjectNavigationMap* pSceneObjectNavigationMap, CXML *pXML, HXMLNODEHANDLE hSceneNode ){
    m_strResourceSpace = strResourceSpace;
    m_pEditorScene = pEditorScene;
    char _strNameBuff[64];
    char _strFileBuff[64];
    char _strBuff0[1024];
    HXMLNODEHANDLE _hHandle = pXML->GetNode( hSceneNode, "sceneobject" );
    _hHandle = pXML->GetNode( _hHandle, "item" );
    while( _hHandle ){
        uint32 _nUUID = pXML->GetAttributeValueUint32( _hHandle, "id" );
        ESceneObjectType _eSceneObjectType = (ESceneObjectType)pXML->GetAttributeValueInt32( _hHandle, "type" );
        int32 _nGridX = pXML->GetAttributeValueInt32( _hHandle, "gridx" );
        int32 _nGridY = pXML->GetAttributeValueInt32( _hHandle, "gridy" );
        const char* _strName = pXML->GetAttributeValue( _hHandle, "name", _strNameBuff );
        const char* _strFile = pXML->GetAttributeValue( _hHandle, "file", _strFileBuff );
        int32 _nCelltype = pXML->GetAttributeValueInt32( _hHandle, "celltype" );
        int32 _nRotationType = pXML->GetAttributeValueInt32( _hHandle, "rotationtype" );        
        float _fInitScale = pXML->GetAttributeValueFloat( _hHandle, "initscale" );
        float _fHelperRadius = pXML->GetAttributeValueFloat( _hHandle, "helperradius" );
        float _vPos[3];
        float _vRotation[3];
        float _vScale[3];
        pXML->GetAttributeValue( _hHandle, "position", _strBuff0 );
        sscanf( _strBuff0, "%f,%f,%f", &_vPos[0], &_vPos[1], &_vPos[2] );
        pXML->GetAttributeValue( _hHandle, "rotation", _strBuff0 );
        sscanf( _strBuff0, "%f,%f,%f", &_vRotation[0], &_vRotation[1], &_vRotation[2] );
        pXML->GetAttributeValue( _hHandle, "scale", _strBuff0 );
        sscanf( _strBuff0, "%f,%f,%f", &_vScale[0], &_vScale[1], &_vScale[2] );
        HXMLNODEHANDLE _hDataNode = pXML->GetFirstNode( _hHandle );
        if( _hDataNode ){
            pXML->GetValue( _hDataNode, _strBuff0 );
        }else{
            _strBuff0[0] = 0;
        }
        CSceneObject* _pSceneObject = AddSceneObject( _nUUID, _strFile, _strName, _eSceneObjectType, _fInitScale, _fHelperRadius, _nCelltype, _nRotationType, _strBuff0, _vPos, _vRotation, _vScale, _nGridX, _nGridY );
        m_nUUID = _nUUID;
        list<TPosition >_vNavigPositionList;
        pSceneObjectNavigationMap->GetCellTypeListValue( _nCelltype, 0, _nGridX, _nGridY, &_vNavigPositionList );
        pSceneObjectNavigationMap->SetSOListValue( &_vNavigPositionList, _pSceneObject );

        _hHandle = pXML->GetNextNode( _hHandle );
    }

    return True;
}
CSceneObject* CSceneObjectManager::AddSceneObject( uint32 nUUID, const char* strFileName, const char* strName, ESceneObjectType eSceneObjectType, float fInitScale, float fHelperRadius, int32 eCellType, int32 nRotationType, const char* strExtData, Vector3 pPos, Vector3 pRotaion, Vector3 pScaltion, int32 nGridX, int32 nGridY ){
    uint32 _nUUID = nUUID;
    if( _nUUID  == 0 ){
        m_nUUID ++;
        _nUUID =  m_nUUID;
    }

    CSceneObject* _pSceneObject = NEW CSceneObject( m_pEditorScene->GetParticleManager(), eSceneObjectType, strExtData );
    _pSceneObject->m_nID = _nUUID;
    _pSceneObject->Init( strFileName, pPos, pRotaion, pScaltion, m_strResourceSpace );
    strncpy( _pSceneObject->m_strName, strName, 32 );
    _pSceneObject->m_fInitScale = fInitScale;
    _pSceneObject->m_fHelperRadius = fHelperRadius;
    _pSceneObject->m_nCellType = eCellType;
    _pSceneObject->m_nRotationType = nRotationType;
    _pSceneObject->m_sMapGridPos.X = nGridX;
    _pSceneObject->m_sMapGridPos.Y = nGridY;
    m_pEditorScene->AddChild( _pSceneObject );
    m_vSceneObjectList.insert( _nUUID, _pSceneObject );
    return _pSceneObject;
}
bool32 CSceneObjectManager::RemoveSceneObject( uint32 nUUID ){
    map<uint32, CSceneObject* >::iterator it = m_vSceneObjectList.find( nUUID );
    if( it != m_vSceneObjectList.end() ){
        CSceneObject* _pSceneObject = it.second();
        m_pEditorScene->RemoveChild( _pSceneObject );
        m_vSceneObjectList.erase( it );
        return True;
    }
    return False;
}
CSceneObject* CSceneObjectManager::GetSceneObject( uint32 nUUID ){
    CSceneObject* _pSceneObject = NULL;
    map<uint32, CSceneObject* >::iterator it = m_vSceneObjectList.find( nUUID );
    if( it != m_vSceneObjectList.end() ){
        _pSceneObject = it.second();
    }
    return _pSceneObject;
}
int32 CSceneObjectManager::GetSceneObject( float fLeft, float fTop, float fRight, float fBottom, list<CSceneObject*>* pSceneObjectList, ESceneObjectType eSceneObjectType ){
    float _fLeft = Min( fLeft, fRight );
    float _fRight = Max( fLeft, fRight );
    float _fTop = Min( fTop, fBottom );
    float _fBottom = Max( fTop, fBottom );
    int32 _nCount = 0;
    for( map<uint32, CSceneObject* >::iterator it = m_vSceneObjectList.begin();
         it != m_vSceneObjectList.end(); it++ ){
        CSceneObject* _pSceneObject = it.second();
        if( _pSceneObject->m_eSceneObjectType == eSceneObjectType ){
            float* _pPos = _pSceneObject->m_vPosition;
            if( PointInRect( _pPos[0], _pPos[2], _fLeft, _fTop, _fRight, _fBottom)){
                pSceneObjectList->push_back( _pSceneObject  );
                _nCount ++;
            }
        }
    }
    return _nCount;
}
bool32 CSceneObjectManager::IsSelectSceneDecorationList( list<CSceneObject*>* pSceneObjectList, float x, float y ){
    for( list<CSceneObject*>::iterator it = pSceneObjectList->begin(); it != pSceneObjectList->end(); it++ ){
        CSceneObject* _pSceneObject = *it;
        float* _pPos = _pSceneObject->m_vPosition;
        float _fBoundRadius = _pSceneObject->m_fHelperRadius;//GetBoundsRadius();
        _fBoundRadius *= _fBoundRadius;
        float _fDis = Distance(_pPos[0], _pPos[2], x, y);
        if( _fDis < _fBoundRadius ){
            return True;
        }
    }
    return False;
}
